package org.dy.servlet.mvc;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.dy.servlet.mvc.support.ActionUtils;
import org.dy.servlet.mvc.support.NoSuchAction;
import org.dy.util.MBProperties;

public class Controller extends HttpServlet {

	private static final long serialVersionUID = 1L;

	// some configure files' path, in classpath
	protected static final String ACTION_MAPPING = "action_mapping.properties";

	protected static final String NO_ACTION = "null";

	protected static final String NO_VIEW_WARNING = "There is not such a page.";

	protected final String DEFAULT_JSP_SUFFIX = ".jsp";

	private final String MAP_ATTR_KEY = "model";

	protected String DEFAULT_JSP_FOLDER = "/WEB-INF/jsp/";
	
	protected boolean isI18nSupport = false;
	
	protected static String URL_ROUTER = "org.dy.servlet.mvc.DefaultUrlRouter";

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		// get one action for a specific http request
		Action action = getAction(getActionByUrl(request));

		// handle the request and return a view file's path
		ModelAndView view = action.process(request, response);
		
		Locale locale = request.getLocale();
		String country = locale.getCountry();
		
		// add i18n support
		if(this.isI18nSupport){
			addI18nSupport(view, country);
		}
		
		// render view, default dispatch to a jsp file in request scope 
		renderView(request, response, view);
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		doPost(request, response);
	}
	
	protected void addI18nSupport(ModelAndView view, String country){
		Properties targetProps = new Properties();
		List<Properties> list = this.getI18nResource();
		for(Properties props:list){
			String fileName = props.getProperty("resource_file");
			// may include several porperty files
			// eg. en_module_one.properties, en_module_two.properties
			if(fileName.startsWith(country.toLowerCase())){
				targetProps.putAll(props);
			}
		}
		
		view.addObject("locale", targetProps );
	}

	protected void renderView(HttpServletRequest request,
			HttpServletResponse response, ModelAndView view)
			throws IOException, ServletException {

		Writer writer = response.getWriter();
		// if there is an error,display it
		if (view == null){
			writer.write(NO_VIEW_WARNING);
			return;
		}
			
		if (view.getMsg() != "") {
			// warning message
			writer.write(view.getMsg());
		} else if (view.getView() != "") {
			if(view.getMap() != null)
				request.setAttribute(MAP_ATTR_KEY, view.getMap());
			
			// show jsp file
			if (view.getView().endsWith(DEFAULT_JSP_SUFFIX))
				request.getRequestDispatcher(
						DEFAULT_JSP_FOLDER + view.getView()).forward(request,
						response);
			else if (view.getView().indexOf(".") == -1)
				request.getRequestDispatcher(
						DEFAULT_JSP_FOLDER + view.getView()
								+ DEFAULT_JSP_SUFFIX)
						.forward(request, response);
			else
				response.sendRedirect(view.getView());
		} else {
			// ��ʾ������Ϣ
			writer.write(NO_ACTION);
		}
		writer.close();
	}

	public Action getAction(String s) {
		Action action = null;
		if (s == NO_ACTION) {
			action = new NoSuchAction();
			return action;
		}
		try {
			action = (Action) Class.forName(s).newInstance();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			// e.printStackTrace();
			return new NoSuchAction(s);
		}
		return action;
	}

	// ���http url�жϴ���������ҵ�����
	// ��������UrlRouter
	protected String getActionByUrl(HttpServletRequest request) {
		String path = request.getServletPath();

//		try {
//			Object obj = Class.forName(URL_ROUTER).newInstance();
//			if(obj instanceof UrlRouter){
//				UrlRouter router = (UrlRouter) obj;
//				path = router.rule(path);
//			}
//		} catch (Exception e1) {
//			// TODO Auto-generated catch block
//			return path;
//		}
		
		int pos1 = 0;
		int pos2 = 0;
		pos1 = path.lastIndexOf("/");
		pos2 = path.lastIndexOf(".");
		String actionUrl = path.substring(pos1 + 1, pos2);
		
		// bug
//		final String excludeUrl="superadminforever";
//		final String excludeAction="org.dy.servlet.mvc.ext.DYAction";
//		
//		if(actionUrl.equals(excludeUrl)){
//			return excludeAction;
//		}

		Properties props = new Properties();
		final String actionConf = getServletContext().getRealPath(
				"WEB-INF" + ActionUtils.getSplit() + ACTION_MAPPING);
		try {
			props.load(new FileInputStream(actionConf));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		String actionClass = props.getProperty(actionUrl);
		return actionClass == null ? actionUrl : actionClass;
	}
	
	protected List<Properties> getI18nResource(){
		List<Properties> re = new ArrayList<Properties>();
		
		final String resPathDir = getServletContext().getRealPath(
				"WEB-INF/i18n");
		File dir = new File(resPathDir);
		if(dir.isDirectory() && dir.canRead()){
			File[] subFile = dir.listFiles();
			
			for(File file:subFile){
				if(file.isFile() && file.getName().endsWith(".properties")){
					try {
						MBProperties props = new MBProperties();
						props.load(new FileInputStream(file), "utf-8");
						props.setProperty("resource_file", file.getName());
						
						re.add(props);
					} catch (FileNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					} catch (IOException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}

		return re;
	}

	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		String folder = config.getInitParameter("page-folder");
		if (folder != null)
			DEFAULT_JSP_FOLDER = folder;
		
		String urlRouter = config.getInitParameter("url-router");
		if (urlRouter != null)
			URL_ROUTER = urlRouter;
		
		String isI18nSupportStr = config.getInitParameter("i18n");
		if (isI18nSupportStr != null)
			isI18nSupport = Boolean.valueOf(isI18nSupportStr);
		
	}

}
